package com.kty.controller;

import com.kty.utils.BenGua;
import com.kty.utils.BianGua;
import com.kty.utils.JiaoYan;
import com.kty.entity.LunarDate;
import com.kty.entity.GregorianDate;
import com.kty.utils.TransFormation;
import cn.hutool.core.date.DateUtil;
import com.kty.entity.ChineseCalendar;
import cn.hutool.core.date.ChineseDate;
import com.kty.entity.SixtyFourTrigram;

public class MHYSController {

    private static final LunarDate nl = new LunarDate(); // 农历日期对象
    private static final GregorianDate gl = new GregorianDate(); // 公历日期对象
    private static final SixtyFourTrigram sft = new SixtyFourTrigram(); // 本卦

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 获取用户录入的信息（默认为 公历日期）
     */
    public static void getGongli() {

        // 获取键盘录入的信息
        int year = JiaoYan.year(); // 公历年
        int month = JiaoYan.month(); // 公历月
        int day = JiaoYan.day(); // 公历日
        int time = JiaoYan.time(); // 公历时

        // 将 农历日期字符串 拼接为字符串
        String data = year + "-" + month + "-" + day;

        // 通过公历构建
        ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate(data));
        // 获取（年月日）天干地支 → 例：辛丑年庚子月己亥日
        // 定义（年月日）柱
        String cyclicalYMD = chineseDate.getCyclicalYMD();

        // 设置 公历日期
        nl.setYear(year);
        nl.setMonth(month);
        nl.setDay(day);
        nl.setTime(time);

        // 设置 农历日期
        gl.setYear(year);
        gl.setMonth(month);
        gl.setDay(day);
        gl.setTime(time);
        nl.setNyr(cyclicalYMD);

    }


    /**
     * 公历日期转换为农历日期
     */
    private static void getGregorianToLunarCalendar() {

        getGongli(); // 获取键盘录入的信息

        int year = gl.getYear(); // 获取 公历年
        int month = gl.getMonth(); // 获取 公历月
        int day = gl.getDay(); // 获取 公历日
        int time = gl.getTime(); // 获取 公历时

        // 调用 < 农历日期转换阳历日期 > 方法
//        System.out.println(ChineseCalendar.sCalendarLundarToSolar(year, month, day)); // 阳历日期字符串（20211218）

        // 调用 < 阳历日期转换农历日期 > 方法
        String lunarCalendar = ChineseCalendar.sCalendarSolarToLundar(year, month, day); // 农历日期字符串（20211115）

        // 截取字符串得出（年月日）
        int newYear = Integer.parseInt(lunarCalendar.substring(0, 4)); // 农历年
        int newMonth = Integer.parseInt(lunarCalendar.substring(4, 6)); // 农历月
        int newDay = Integer.parseInt(lunarCalendar.substring(6, 8)); // 农历日

        // 将 农历日期字符串 拼接为字符串
        String data = newYear + "-" + newMonth + "-" + newDay;

        // 通过公历构建
        ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate(data));
        // 获取（年月日）天干地支 → 例：辛丑年庚子月己亥日
        // 定义（年月日）柱
        String cyclicalYMD = chineseDate.getCyclicalYMD();

        // 设置 农历日期
        nl.setYear(newYear); // 设置农历年
        nl.setMonth(newMonth); // 设置农历月
        nl.setDay(newDay); // 设置农历日
        nl.setTime(time); // 设置农历时
        nl.setNyr(cyclicalYMD); // 设置农历（年月日）柱

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 1、根据农历 → 计算 '年数'：判断 年地支 并获取 '年数'
     */
    public static int getYears() {

        // 获取 年地支字符串
        String dz = nl.getDz();

        // 截取 '年地支'
        String annualBranch = nl.getNyr().substring(1, 2);

        // 初始化变量，用于记录索引
        int index = 0;

        // 判断 '年地支' 在年地支字符串中的索引位置
        for (int i = 0; i < dz.length(); i++) {
            // 取出字符串中的每一个元素
            String s = String.valueOf(dz.charAt(i));
            // 比较，若相同，则返回该元素对应的索引值
            if (s.equals(annualBranch)) {
                index = dz.indexOf(annualBranch); // 该元素（地支）对应的索引值
                break;
            }
        }
        // 返回 农历'年数'
        return (index + 1);

    }


    /**
     * 2、根据农历 → 计算 '月数'
     */
    public static int getMonths() {

        // 获取 农历'月数'
        return nl.getMonth();

    }


    /**
     * 3、根据农历 → 计算 '日数'
     */
    public static int getDays() {

        // 获取 农历'日数'
        return nl.getDay();

    }


    /**
     * 4、根据农历 → 计算 '时数'：判断时间范围并获取 '时数'
     *
     * @return
     */
    private static int getHours() {

        // 获取 农历 '时间'
        int time = nl.getTime();

        if (time >= 1 && time < 3) {
            return 2; // 1:00:00-2:59:59 → 丑时（时数为2）
        }
        if (time >= 3 && time < 5) {
            return 3; // 3:00:00-4:59:59 → 阴时（时数为3）
        }
        if (time >= 5 && time < 7) {
            return 4; // 5:00:00-6:59:59 → 卯时（时数为4）
        }
        if (time >= 7 && time < 9) {
            return 5; // 7:00:00-8:59:59 → 辰时（时数为5）
        }
        if (time >= 9 && time < 11) {
            return 6; // 9:00:00-10:59:59 → 巳时（时数为6）
        }
        if (time >= 11 && time < 13) {
            return 7; // 11:00:00-12:59:59 → 午时（时数为7）
        }
        if (time >= 13 && time < 15) {
            return 8; // 13:00:00-14:59:59 → 未时（时数为8）
        }
        if (time >= 15 && time < 17) {
            return 9; // 15:00:00-16:59:59 → 申时（时数为9）
        }
        if (time >= 17 && time < 19) {
            return 10; // 17:00:00-18:59:59 → 酉时（时数为10）
        }
        if (time >= 19 && time < 21) {
            return 11; // 19:00:00-20:59:59 → 戌时（时数为11）
        }
        if (time >= 21 && time < 23) {
            return 12; // 21:00:00-22:59:59 → 亥时（时数为12）
        }
        return 1; // 23:00:00-00:59:59 → 子时（时数为1）

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 一、计算《上卦数》
     * <p>
     * （年数 + 月数 + 日数）/ 8得出 余数
     * <p>
     * 注意：上卦数若全部除尽，则统一用 坤卦(8) 来表示
     */
    public static int getUpperHexagramNumber() {

        int uhn = (getYears() + getMonths() + getDays()) % 8; // 上卦数

        // 判断是否除尽
        if (uhn == 0) {
            return 8;
        }
        return uhn;

    }


    /**
     * 二、计算《下卦数》
     * <p>
     * （年数 + 月数 + 日数 + 时数）/ 8得出 余数
     * <p>
     * 注意：下卦数若全部除尽，则统一用 坤卦(8) 来表示
     */
    public static int getDivinationNumber() {

        int dtu = (getYears() + getMonths() + getDays() + getHours()) % 8; // 下卦数

        // 判断是否除尽
        if (dtu == 0) {
            return 8;
        }
        return dtu;

    }


    /**
     * 三、计算《动爻数》
     * <p>
     * （年数 + 月数 + 日数 + 时数）/ 6得出 余数
     * <p>
     * 注意：动爻若全部除尽，则统一用 六爻(6) 来表示
     */
    public static int getMove() {

        int move = (getYears() + getMonths() + getDays() + getHours()) % 6; // 动爻数

        // 判断是否除尽
        if (move == 0) {
            return 6;
        }
        return move;

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * ★ 根据《上卦数》获取 上卦对应'八卦'
     */
    public static String upBaGua() {

        int upTg = getUpperHexagramNumber(); // 上卦数（索引）

        return getBaGua(upTg);

    }


    /**
     * ★根据《下卦数》获取 下卦对应'八卦'
     */
    public static String downBaGua() {

        int upTg = getDivinationNumber(); // 下卦数（索引）

        return getBaGua(upTg);

    }


    /**
     * ★ 动爻
     */
    public static int move() {

        return getMove(); // 动爻数

    }


    /**
     * 通过（上、下）卦数输出应的八卦
     *
     * @param upTg
     * @return
     */
    private static String getBaGua(int upTg) {

        String baGua = nl.getCongenitalgossip(); // 八卦字符串

        String bg = null; // 定义临时变量，用于接收 '八卦'
        // 遍历 八卦字符串
        for (int i = 0; i < baGua.length(); i++) {
            // 取出上卦数（索引）对应的八卦（元素）
            bg = String.valueOf(baGua.charAt(upTg - 1));
        }
        return bg;

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * ☆ 本卦：（上卦 + 下卦）得出
     * <p>
     * --->如：
     * 上兑（☱）下离（☲）
     * ☆本卦：（䷰）
     */
    public static String benGua() {

        return BenGua.benGua();

    }


    /**
     * ☆ 变卦：根据 '动爻数' 从 本卦 自下向上数 数字
     * <p>
     * --->如：
     * 本卦：（䷰）
     * 动爻：1(向上数第一爻:阳爻变阴爻,阴爻变阳爻)
     * ☆变卦：泽山咸卦（䷞）
     */
    public static String bianGua() {

        return BianGua.bianGua();

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 判断 上卦图形
     */
    public static String shangguaFigure() {

        // 获取 '上卦数'
        int sgs = getUpperHexagramNumber();

        return tuXing(sgs);

    }


    /**
     * 判断 下卦图形
     */
    public static String xiaguaFigure() {

        // 获取 '下卦数'
        int xgs = getDivinationNumber();

        return tuXing(xgs);

    }


    /**
     * 判断 （上、下）卦 对应图形
     *
     * @param xgs
     * @return
     */
    private static String tuXing(int xgs) {

        // 定义临时变量，用于保存 八卦图形
        String sg = null;
        // 输出对应图形
        for (int i = 0; i < sft.getBg().length(); i++) {
            sg = String.valueOf(sft.getBg().charAt(xgs - 1));
        }
        return sg;

    }


    /**
     * 判断 本卦图形
     */
    private static String benGuaFigure() {

        return BenGua.benGuaTu();

    }


    /**
     * 判断 变卦图形
     */
    private static String bianGuaFigure() {

        return BianGua.bianGuaTu();

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 公历日期 转 农历日期 → 测算
     */
    public static void gongLiToNongLi() {

        getGregorianToLunarCalendar(); // 公历日期 转 农历日期

        System.out.println("\n------------------------公历转农历------------------------");
        System.out.println("--->公历 " + gl);
        System.out.println("--->农历 " + nl);
        System.out.println("\n年数：" + getYears() +
                "，月数：" + getMonths() +
                "，日数：" + getDays() +
                "，时数：" + getHours());

        System.out.println("-----------------");
        jieGuo();

    }


    /**
     * 公历日期 或 农历日期 → 测算
     */
    public static void gongLiOrNongLi() {

        getGongli();

        System.out.println("\n------------------------公历或农历------------------------");
        System.out.println("--->公(农)历 " + gl);
        System.out.println("\n年数：" + getYears() +
                "，月数：" + getMonths() +
                "，日数：" + getDays() +
                "，时数：" + getHours());

        System.out.println("-----------------");
        jieGuo();

    }

//----------------------------------------------------------------------------------------------------------------------

    /**
     * 输出结果
     */
    public static void jieGuo() {

        int upperHexagramNumber = getUpperHexagramNumber(); // 上卦数
        System.out.println("上卦数：" + upperHexagramNumber);

        int divinationNumber = getDivinationNumber(); // 下卦数
        System.out.println("下卦数：" + divinationNumber);

        int move = getMove(); // 动爻数
        System.out.println("动爻数：" + move);

        System.out.println("-----------------");
//------------------------------------------------------------------------

        String sg = upBaGua(); // 上卦
        String sgtx = shangguaFigure(); // 上卦图形
        System.out.println("上卦：" + sg + "（" + sgtx + "）");

        String xg = downBaGua(); // 下卦
        String xgtx = xiaguaFigure(); // 下卦图形
        System.out.println("下卦：" + xg + "（" + xgtx + "）");

        int dy = move(); // 动爻数
        String dongYao = TransFormation.transfer(dy); // 将 数字 转换为 汉字
        System.out.println("动爻：" + dongYao + "爻爻动");

        System.out.println("-----------------");
//------------------------------------------------------------------------

        System.out.println("本卦：" + benGua() + "（" + benGuaFigure() + "）");

        System.out.println("变卦：" + bianGua() + "（" + bianGuaFigure() + "）");

    }


}
